﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;

namespace Rapid.Utility.Helper
{
    /// <summary>
    /// Http处理
    /// </summary>
    public static class HttpHelper
    {
        #region HttpContext

        /// <summary>
        /// Http 上下文
        /// </summary>
        public static HttpContext Context
        {
            get { return HttpContext.Current; }
        }

        /// <summary>
        /// Http 客户端请求
        /// </summary>
        public static HttpRequest Request
        {
            get { return Context.Request; }
        }

        /// <summary>
        /// Http 服务端响应
        /// </summary>
        public static HttpResponse Response
        {
            get { return Context.Response; }
        }

        /// <summary>
        /// 请求内容主体
        /// </summary>
        public static Stream InputStream
        {
            get { return Request.InputStream; }
        }

        /// <summary>
        /// 是否是Get类型请求
        /// </summary>
        public static bool IsGet
        {
            get { return string.Compare(Request.HttpMethod, "get", true) == 0; }
        }

        /// <summary>
        /// 是否是Post类型请求
        /// </summary>
        public static bool IsPost
        {
            get { return string.Compare(Request.HttpMethod, "post", true) == 0; }
        }

        /// <summary>
        /// 获取物理路径
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static string MapPath(string path)
        {
            return Context.Server.MapPath(path);
        }

        #endregion

        #region HttpContext Method

        /// <summary>
        /// 获取路径参数
        /// </summary>
        /// <param name="key">键值</param>
        /// <returns>参数</returns>
        public static string QueryString(string key)
        {
            return Request.QueryString[key];
        }

        /// <summary>
        /// 获取表单参数
        /// </summary>
        /// <param name="key">键值</param>
        /// <returns>参数</returns>
        public static string Form(string key)
        {
            return Request.Form[key];
        }

        /// <summary>
        /// 清空响应
        /// </summary>
        public static void ResponseClear()
        {
            Response.Clear();
        }

        /// <summary>
        /// 输出内容
        /// </summary>
        /// <param name="obj">内容</param>
        public static void ResponseWrite(object obj)
        {
            Response.Write(obj);
        }

        /// <summary>
        /// 结束响应
        /// </summary>
        public static void ResponseEnd()
        {
            Response.End();
        }

        public static void Redirect(string uri)
        {
            Response.Clear(); Response.Redirect(uri); Response.End();
        }

        #endregion

        #region HttpRequest IPAddress

        /// <summary>
        /// 信息内容
        /// </summary>
        public class IPAdderssData
        {
            public string country;

            public string country_id;

            public string area;

            public string area_id;

            public string region;

            public string region_id;

            public string city;

            public string city_id;

            public string county;

            public string county_id;

            public string isp;

            public string isp_id;

            public string ip;
        }

        /// <summary>
        /// 基础数据
        /// </summary>
        public class IPCheckResult
        {
            public int code;

            public IPAdderssData data;
        }

        /// <summary> 
        /// 取得客户端真实IP地址
        /// </summary> 
        public static string IPAddress
        {
            get
            {
                string result = string.Empty;
                string temp = string.Empty;

                result = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];

                if (!string.IsNullOrEmpty(result))
                {
                    //可能有代理 
                    if (result.IndexOf(".") != -1) //没有“.”肯定是非IPv4格式 
                    {
                        if (result.IndexOf(",") != -1) { return result; }
                        else if (IsIPAddress(result)) { return result; } //代理即是IP格式 
                        else { result = null; } //代理中的内容 非IP，取IP 
                    }
                    else { result = null; }
                }

                if (string.IsNullOrEmpty(result))
                {
                    result = Request.ServerVariables["REMOTE_ADDR"];
                }
                if (string.IsNullOrEmpty(result))
                {
                    result = Request.UserHostAddress;
                }

                return result;
            }
        }

        /// <summary> 
        /// 判断是否是IP地址格式 0.0.0.0 
        /// </summary> 
        /// <param name="ip">待判断的IP地址</param> 
        /// <returns>true or false</returns> 
        public static bool IsIPAddress(string ip)
        {
            if (string.IsNullOrEmpty(ip) || ip.Length < 7 || ip.Length > 15) { return false; }

            string regformat = @"^\d{1,3}[\.]\d{1,3}[\.]\d{1,3}[\.]\d{1,3}$";

            Regex regex = new Regex(regformat, RegexOptions.IgnoreCase);

            return regex.IsMatch(ip);
        }

        /// <summary>
        /// 获取IP所在区域
        /// </summary>
        /// <param name="ip">IP地址</param>
        /// <returns>结果</returns>
        public static IPCheckResult IPInfo(string ip)
        {
            if (!IsIPAddress(ip)) { return null; }

            string url = string.Format("http://ip.taobao.com/service/getIpInfo.php?ip={0}", ip);

            string json = ResponseString(GetResponse(url));

            return JsonConvert.DeserializeObject<IPCheckResult>(json);
        }

        #endregion

        #region HttpWebResponse Simulation

        /// <summary>  
        /// 创建GET方式的HTTP请求  
        /// </summary>  
        public static HttpWebResponse GetResponse(string url, int timeout = 5000, string userAgent = null, CookieCollection cookies = null)
        {
            HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;

            request.Method = "GET";

            //设置代理UserAgent和超时
            request.UserAgent = userAgent;
            request.Timeout = timeout;

            if (cookies != null)
            {
                request.CookieContainer = new CookieContainer();
                request.CookieContainer.Add(cookies);
            }

            return request.GetResponse() as HttpWebResponse;
        }

        /// <summary>  
        /// 创建POST方式的HTTP请求  
        /// </summary>  
        public static HttpWebResponse PostResponse(string url, string parameters, int timeout = 5000, string userAgent = null, CookieCollection cookies = null)
        {
            HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;

            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";

            //设置代理UserAgent和超时
            request.UserAgent = userAgent;
            request.Timeout = timeout;

            if (cookies != null)
            {
                request.CookieContainer = new CookieContainer();
                request.CookieContainer.Add(cookies);
            }

            //发送POST数据  
            if (parameters != null)
            {
                byte[] data = Encoding.UTF8.GetBytes(parameters);
                using (Stream stream = request.GetRequestStream())
                {
                    stream.Write(data, 0, data.Length);
                }
            }

            string[] values = request.Headers.GetValues("Content-Type");
            return request.GetResponse() as HttpWebResponse;
        }

        /// <summary>  
        /// 创建POST方式的HTTP请求发送文件 
        /// </summary>  
        public static HttpWebResponse PostFileResponse(string url, Dictionary<string, string> fileDictionary, int timeout = 5000, string userAgent = null, CookieCollection cookies = null)
        {
            HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;

            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            request.KeepAlive = true;

            //设置代理UserAgent和超时
            request.UserAgent = userAgent;
            request.Timeout = timeout;

            if (cookies != null)
            {
                request.CookieContainer = new CookieContainer();
                request.CookieContainer.Add(cookies);
            }

            #region 处理Form表单文件上传

            Stream postStream = null;

            var formUploadFile = fileDictionary.Count > 0;

            if (formUploadFile)
            {
                postStream = new MemoryStream();
                string boundary = "----" + DateTime.Now.Ticks.ToString("x");
                string formdataTemplate = "\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: application/octet-stream\r\n\r\n";

                foreach (var file in fileDictionary)
                {
                    try
                    {
                        //准备文件流
                        using (FileStream fileStream = new FileStream(file.Value, FileMode.Open))
                        {
                            var formdata = string.Format(formdataTemplate, file.Key, file.Value);
                            var formdataBytes = Encoding.ASCII.GetBytes(postStream.Length == 0 ? formdata.Substring(2, formdata.Length - 2) : formdata);
                            postStream.Write(formdataBytes, 0, formdataBytes.Length);

                            //写入文件
                            byte[] buffer = new byte[1024];
                            int bytesRead = 0;
                            while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
                            {
                                postStream.Write(buffer, 0, bytesRead);
                            }
                        }
                    }
                    catch (Exception ex) { throw ex; }
                }
                //结尾
                var footer = Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
                postStream.Write(footer, 0, footer.Length);

                request.ContentType = string.Format("multipart/form-data; boundary={0}", boundary);
            }
            else
            {
                request.ContentType = "application/x-www-form-urlencoded";
            }

            #endregion

            request.ContentLength = postStream != null ? postStream.Length : 0;

            #region 输入二进制流

            if (postStream != null)
            {
                postStream.Position = 0;

                //直接写入流
                Stream requestStream = request.GetRequestStream();

                byte[] buffer = new byte[1024];
                int bytesRead = 0;
                while ((bytesRead = postStream.Read(buffer, 0, buffer.Length)) != 0)
                {
                    requestStream.Write(buffer, 0, bytesRead);
                }

                postStream.Close(); postStream.Dispose();
            }

            #endregion

            string[] values = request.Headers.GetValues("Content-Type");
            return request.GetResponse() as HttpWebResponse;
        }

        /// <summary>
        /// 创建POST方式的WebAPI的HTTP请求  
        /// </summary>
        public static HttpWebResponse PostAPIResponse(string url, string parameters, int timeout, string userAgent, CookieCollection cookies)
        {
            HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;

            request.Method = "POST";
            request.ContentType = "application/json";

            //设置代理UserAgent和超时
            request.UserAgent = userAgent;
            request.Timeout = timeout;

            if (cookies != null)
            {
                request.CookieContainer = new CookieContainer();
                request.CookieContainer.Add(cookies);
            }

            //发送POST数据  
            if (parameters != null)
            {
                byte[] data = Encoding.UTF8.GetBytes(parameters);
                using (Stream stream = request.GetRequestStream())
                {
                    stream.Write(data, 0, data.Length);
                }
            }

            string[] values = request.Headers.GetValues("Content-Type");
            return request.GetResponse() as HttpWebResponse;
        }

        /// <summary>
        /// 创建POST方式的带证书的HTTP请求  
        /// </summary>
        public static HttpWebResponse PostCertResponse(string url, X509Certificate2 cert, string data, int timeout = 100000, string userAgent = null)
        {
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
            request.ClientCertificates.Add(cert);
            request.Method = "POST";

            //设置代理UserAgent和超时
            request.UserAgent = userAgent;
            request.Timeout = timeout;

            byte[] postdatabyte = Encoding.UTF8.GetBytes(data);
            request.ContentLength = postdatabyte.Length;

            using (Stream stream = request.GetRequestStream())
            {
                stream.Write(postdatabyte, 0, postdatabyte.Length);
            }

            return request.GetResponse() as HttpWebResponse;
        }

        /// <summary>
        /// 获取请求的数据
        /// </summary>
        public static string ResponseString(HttpWebResponse webresponse)
        {
            using (Stream s = webresponse.GetResponseStream())
            {
                StreamReader reader = new StreamReader(s, Encoding.UTF8);
                return reader.ReadToEnd();
            }
        }

        /// <summary>  
        /// 创建GET方式的HTTP请求并返回结果
        /// </summary>  
        public static string Get(string url, int timeout = 5000, string userAgent = null, CookieCollection cookies = null)
        {
            return ResponseString(GetResponse(url, timeout, userAgent, cookies));
        }

        /// <summary>  
        /// 创建POST方式的HTTP请求并返回结果
        /// </summary>  
        public static string Post(string url, string parameters, int timeout = 5000, string userAgent = null, CookieCollection cookies = null)
        {
            return ResponseString(PostResponse(url, parameters, timeout, userAgent, cookies));
        }

        /// <summary>
        /// 使用Post方法获取字符串结果
        /// </summary>
        public static string PostFile(string url, Dictionary<string, string> fileDictionary, int timeout = 5000, string userAgent = null, CookieCollection cookies = null)
        {
            return ResponseString(PostFileResponse(url, fileDictionary, timeout, userAgent, cookies));
        }

        /// <summary>
        /// 创建POST方式的HTTP请求并返回结果
        /// </summary>
        public static string PostAPI(string url, string parameters, int timeout, string userAgent, CookieCollection cookies)
        {
            return ResponseString(PostAPIResponse(url, parameters, timeout, userAgent, cookies));
        }

        /// <summary>
        /// 创建POST方式的带证书的HTTP请求并返回结果
        /// </summary>
        public static string PostCert(string url, X509Certificate2 cert, string data, int timeout = 100000, string userAgent = null)
        {
            return ResponseString(PostCertResponse(url, cert, data, timeout, userAgent));
        }

        /// <summary>
        /// 对URL字符串进行编码
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static string UrlEncode(string url)
        {
            return HttpUtility.UrlEncode(url);
        }

        /// <summary>
        /// 对URL字符串进行解码
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static string UrlDecode(string url)
        {
            return HttpUtility.UrlDecode(url);
        }

        /// <summary>
        /// 下载文件
        /// </summary>
        public static void Download(string url, Stream stream)
        {
            using (WebClient wc = new WebClient())
            {
                var data = wc.DownloadData(url);
                foreach (var b in data)
                {
                    stream.WriteByte(b);
                }
            }
        }

        /// <summary>
        /// 下载文件（Post请求）
        /// </summary>
        public static void Download(string url, string parameters, Stream stream)
        {
            WebClient wc = new WebClient();
            var file = wc.UploadData(url, "POST", Encoding.UTF8.GetBytes(string.IsNullOrEmpty(parameters) ? "" : parameters));
            foreach (var b in file)
            {
                stream.WriteByte(b);
            }
        }

        #region 从文件系统中下载文件

        /// <summary>
        /// 下载文件
        /// </summary>
        /// <param name="exportFilePath">文件路径</param>
        ///<param name="isDelete">是否删除本地文件</param>
        public static void UserDownLoad(string exportFilePath, bool isDelete)
        {
            FileInfo fileInfo = new FileInfo(exportFilePath);
            string filePath = Path.GetFileName(fileInfo.FullName);
            string newPath = HttpContext.Current.Server.UrlEncode(filePath); //将路径进行编码，否则如果压缩包是中文的话，会出现乱码
            HttpContext.Current.Response.Clear();
            HttpContext.Current.Response.ClearHeaders();
            HttpContext.Current.Response.Buffer = false;
            HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment;filename=" + newPath);
            HttpContext.Current.Response.AddHeader("Content-Length", fileInfo.Length.ToString());
            HttpContext.Current.Response.AddHeader("Content-Transfer-Encoding", "binary");
            HttpContext.Current.Response.ContentType = "application/octet-stream";
            HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.Default;
            HttpContext.Current.Response.WriteFile(fileInfo.FullName);
            HttpContext.Current.Response.Flush();
            if (isDelete)
            {
                File.Delete(exportFilePath);
            }
            HttpContext.Current.Response.End();
        }

        #endregion

        #region 从内存中下载文件

        /// <summary>
        /// 下载文件
        /// </summary>
        /// <param name="fileName">文件名称</param>
        public static void UserDownLoad(string fileName, MemoryStream stream)
        {
            string newFileName = HttpContext.Current.Server.UrlEncode(fileName);//将路径进行编码，否则如果压缩包是中文的话，会出现乱码
            HttpContext.Current.Response.Clear();
            HttpContext.Current.Response.ClearHeaders();
            HttpContext.Current.Response.Buffer = false;
            HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment;filename=" + newFileName);
            HttpContext.Current.Response.AddHeader("Content-Length", stream.ToArray().Length.ToString());
            HttpContext.Current.Response.AddHeader("Content-Transfer-Encoding", "binary");
            HttpContext.Current.Response.ContentType = "application/octet-stream";
            HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.Default;
            HttpContext.Current.Response.BinaryWrite(stream.ToArray());
            HttpContext.Current.Response.Flush();
            HttpContext.Current.Response.End();
        }

        #endregion

        /// <summary>
        /// 验证证书
        /// </summary>
        private static bool ValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        {
            if (errors == SslPolicyErrors.None) { return true; } else { return false; }
        }

        #endregion
    }
}